/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.liquidByte.trafficMustang.server.business;

import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import org.liquidByte.trafficMustang.server.dataModel.*;
import org.liquidByte.trafficMustang.server.dataModel.enums.TrechoSituacao;
import org.liquidByte.trafficMustang.server.repository.TrechoRepository;
import org.liquidByte.trafficMustang.server.services.*;

/**
 *
 * @author Alexandre
 */
@Stateless
public class TrechoBO implements TrechoService {

    @EJB
    private TrechoRepository repository;
    @EJB
    private LoginService loginService;
    @EJB
    private AvaliacaoService avaliacaoService;
    @EJB
    private DeslocamentoService deslocamentoService;
    @EJB
    private MainService mainService;
    
    public void embarque(Localizacao localizacao, Trecho trecho) throws BusinessException {
        Usuario usr = this.loginService.getUsuario();
        if (localizacao == null) {
            throw new BusinessException("Não foi possível detectar sua localização");
        }              
        if (usr == null || usr.getPassageiro() == null || !usr.getPassageiro().equals(trecho.getPasgId())) {
            throw new BusinessException("Somente o passageiro pode embarcar");
        }
        if (trecho.getTrecSitId() != TrechoSituacao.Confirmado) {
            throw new BusinessException("Só é possível embarcar quando confirmado");
        }

        trecho.setTrecSitId(TrechoSituacao.Embarcado);
        trecho.setEmbarque(localizacao);
        
        this.repository.persist(trecho);
    }

    public void cancelar(Trecho trecho) throws BusinessException {
        Usuario usr = this.loginService.getUsuario();
        if (usr == null || usr.getPassageiro() == null || !usr.getPassageiro().equals(trecho.getPasgId())) {
            throw new BusinessException("Somente o passageiro pode desembarcar");
        }
        
        if (this.isFinalState(trecho)) {
            throw new BusinessException("Esse trecho não pode ser cancelado devido à sua situação");
        } else if (trecho.getTrecSitId() == TrechoSituacao.Embarcado) {
            throw new BusinessException("Para cancelar o trecho, marque o desembarque");
        } else if (trecho.getTrecSitId() == TrechoSituacao.Confirmado) {
            trecho.setTrecSitId(TrechoSituacao.Cancelado);
            this.repository.persist(trecho);
            this.deslocamentoService.decrementarLotacao(trecho.getDeslcId());
            this.avaliacaoService.nova(trecho);
        } else if (trecho.getTrecSitId() == TrechoSituacao.Solicitado) {
            trecho.setTrecSitId(TrechoSituacao.Cancelado);
            this.repository.persist(trecho);
            
            this.mainService.aceiteRemove(trecho.getDeslcId().getMotrId(), trecho);
        }
    }

    public void desembarque(Localizacao localizacao, Trecho trecho) throws BusinessException {
        Usuario usr = this.loginService.getUsuario();
        if (localizacao == null) {
            throw new BusinessException("Não foi possível detectar sua localização");
        }                         
        if (usr == null || usr.getPassageiro() == null || !usr.getPassageiro().equals(trecho.getPasgId())) {
            throw new BusinessException("Somente o passageiro pode desembarcar");
        }
        if (trecho.getTrecSitId() != TrechoSituacao.Embarcado) {
            throw new BusinessException("Só é possível desembarcar quando embarcado");
        }

        trecho.setTrecSitId(TrechoSituacao.Desembarcado);
        trecho.setDesembarque(localizacao);
        
        this.repository.persist(trecho);
        this.deslocamentoService.decrementarLotacao(trecho.getDeslcId());
        this.avaliacaoService.nova(trecho);
    }

    public void confirmar(Trecho trecho) throws BusinessException {
        Usuario usr = this.loginService.getUsuario();
        if (usr == null || usr.getMotorista() == null || !usr.getMotorista().equals(trecho.getDeslcId().getMotrId())) {
            throw new BusinessException("Somente o motorista pode confirmar uma carona");
        }
        if (trecho.getTrecSitId() != TrechoSituacao.Solicitado) {
            throw new BusinessException("Só é possível confirmar uma carona no estado solicitada");
        }
        
        trecho.setTrecSitId(TrechoSituacao.Confirmado);
        this.repository.persist(trecho);
        this.deslocamentoService.incrementarLotacao(trecho.getDeslcId());
        
        this.mainService.trechoPut(trecho.getPasgId(), trecho);
    }
    
    public void negar(Trecho trecho) throws BusinessException {
        Usuario usr = this.loginService.getUsuario();
        if (usr == null || usr.getMotorista() == null || !usr.getMotorista().equals(trecho.getDeslcId().getMotrId())) {
            throw new BusinessException("Somente o motorista pode confirmar uma carona");
        }
        if (trecho.getTrecSitId() != TrechoSituacao.Solicitado) {
            throw new BusinessException("Só é possível negar uma carona no estado solicitada");
        }
        
        trecho.setTrecSitId(TrechoSituacao.Negado);
        this.repository.persist(trecho);
        
        this.mainService.trechoRemove(trecho.getPasgId(), trecho);
        this.mainService.messagePut(trecho.getPasgId().getUsuario(), "Negado", "O trecho foi negado");
    }

    public void requisitar(Deslocamento deslocamento) throws BusinessException {
        Usuario usr = this.loginService.getUsuario();
        if (usr == null) {
            throw new BusinessException("Usuário não identificado");
        } else if (usr.getPassageiro() == null) {
            throw new BusinessException("Passageiro não identificado");
        }
        Trecho requisicao = new Trecho();
        requisicao.setDeslcId(deslocamento);
        requisicao.setPasgId(usr.getPassageiro());
        requisicao.setTrecSitId(TrechoSituacao.Solicitado);
        
        this.repository.persist(requisicao);

        this.repository.flush();
        this.mainService.aceitePut(deslocamento.getMotrId(), requisicao);
    }

    public List<Trecho> getPendente(Motorista motorista) {
        return this.repository.get(motorista, TrechoSituacao.Solicitado);
    }

    public List<Trecho> getPendente(Passageiro passageiro) {
        return this.repository.get(passageiro, TrechoSituacao.Solicitado,
                                               TrechoSituacao.Confirmado,
                                               TrechoSituacao.Embarcado);
    }

    public boolean existePendencia(Passageiro passageiro) {
        return this.getPendente(passageiro).size() > 0;
    }

    public void abortar(Trecho trecho) {
        if (trecho.getTrecSitId() == TrechoSituacao.Confirmado ||
            trecho.getTrecSitId() == TrechoSituacao.Embarcado) {
            trecho.setTrecSitId(TrechoSituacao.Cancelado);
            this.repository.persist(trecho);
            this.avaliacaoService.nova(trecho);
            this.mainService.trechoRemove(trecho.getPasgId(), trecho);
        } else if (trecho.getTrecSitId() == TrechoSituacao.Solicitado) {
            trecho.setTrecSitId(TrechoSituacao.Cancelado);
            this.repository.persist(trecho);
            this.mainService.trechoRemove(trecho.getPasgId(), trecho);
        }
    }

    public boolean isFinalState(Trecho trecho) {
        return trecho.getTrecSitId() == TrechoSituacao.Cancelado ||
               trecho.getTrecSitId() == TrechoSituacao.Desembarcado ||
               trecho.getTrecSitId() == TrechoSituacao.Negado;
    }
}
